# app/services/server_service.py
from app import db
from app.models import Server, Channel, ServerMember, ChannelPermission, User,GuestUser, Friend
import uuid
from sqlalchemy.orm import joinedload


class ServerService:
    @staticmethod
    def create_server(name, owner_id):
        """创建新服务器"""

        # 生成邀请码（简化版）
        def generate_invite_code():
            return str(uuid.uuid4().hex)[:12].upper()

        server_id = str(uuid.uuid4())

        new_server = Server(
            server_id=server_id,
            name=name,
            owner_id=owner_id,
            invite_code=generate_invite_code(),
            is_default=False
        )
        db.session.add(new_server)

        # 创建默认频道
        templates = [
            {
                'name': '综合',
                'type': 'text',
                'position': 1
            },
            {
                'name': '公告',
                'type': 'text',
                'position': 2
            },
            {
                'name': '游戏',
                'type': 'text',
                'position': 3
            },
            {
                'name': '闲聊',
                'type': 'voice',
                'position': 1
            },
            {
                'name': '游戏',
                'type': 'voice',
                'position': 2
            },
            {
                'name': '音乐',
                'type': 'voice',
                'position': 3
            }
        ]
        for template in templates:
            new_channel = Channel(
                channel_id=str(uuid.uuid4()),
                server_id=new_server.server_id,
                name=template['name'],
                type=template['type'],
                position=template['position']
            )
            db.session.add(new_channel)

        # 使用第一个文本频道作为活跃频道
        text_channel = Channel.query.filter_by(
            server_id=new_server.server_id,
            type='text'
        ).order_by('position').first()

        act_channel = str(text_channel.channel_id) if text_channel else None


        # 添加所有者为成员
        membership = ServerMember(
            membership_id=str(uuid.uuid4()),
            server_id=new_server.server_id,
            user_id=owner_id,
            actChannel=act_channel,
            role='owner',
            can_leave=True
        )
        db.session.add(membership)

        #为成员创建默认频道权限
        channels = Channel.query.filter_by(server_id=new_server.server_id).all()

        for channel in channels:
            permission = ChannelPermission(
                permission_id=str(uuid.uuid4()),
                channel_id=channel.channel_id,
                member_id=membership.membership_id,
                can_view=True,
                can_send=(channel.type == 'text'),  # 文本频道可发送消息
                can_connect=(channel.type == 'voice')  # 语音频道可连接
            )
            db.session.add(permission)
        db.session.commit()
        return new_server

    @staticmethod
    def get_default_server():
        """获取默认服务器"""
        return Server.query.filter_by(is_default=True).first()

    @staticmethod
    def join_server(user_id, invite_code):
        """通过邀请码加入服务器"""
        server = Server.query.filter_by(invite_code=invite_code).first()
        if not server:
            return '邀请码不存在', 404

        # 检查是否已是成员
        if ServerMember.query.filter_by(server_id=server.server_id, user_id=user_id).first():
            return '已在该服务器中', 400

        # 使用第一个文本频道作为活跃频道
        text_channel = Channel.query.filter_by(
            server_id=server.server_id,
            type='text'
        ).order_by('position').first()

        act_channel = str(text_channel.channel_id) if text_channel else None

        # 添加成员
        membership = ServerMember(
            membership_id=str(uuid.uuid4()),
            server_id=server.server_id,
            user_id=user_id,
            role='member',
            actChannel=act_channel,
            can_leave=True,
        )
        db.session.add(membership)

        # 为成员创建默认频道权限
        channels = Channel.query.filter_by(server_id=server.server_id).all()

        for channel in channels:
            permission = ChannelPermission(
                permission_id=str(uuid.uuid4()),
                channel_id=channel.channel_id,
                member_id=membership.membership_id,
                can_view=True,
                can_send=True,
                can_connect=True
            )
            db.session.add(permission)

        db.session.commit()
        return server

    @staticmethod
    def exit_server(user_id, server_id):
        """退出服务器"""
        server = Server.query.filter_by(server_id=server_id).first()
        user = User.query.filter_by(user_id=user_id).first()
        if not server:
            return '服务器不存在', 404

        membership = ServerMember.query.filter_by(
            server_id=server_id,
            user_id=user_id
        ).first()

        if not membership.can_leave:
            return '不允许主动退出该服务器', 403

        ChannelPermission.query.filter_by(member_id=membership.membership_id).delete()
        db.session.delete(membership)

        remaining_members = ServerMember.query.filter_by(server_id=server_id).count()

        user.actServer = 'server_default'

        result = {
            'name': server.name,
        }

        db.session.commit()
        return result

    @staticmethod
    def get_servers_by_user(user_id: str,userType:str):
        """
        根据用户ID获取该用户加入的所有服务器
        包括服务器基本信息、默认频道和成员数
        """
        try:
            # 查询用户加入的所有服务器成员关系
            server_memberships = None
            if userType == 'guestUser':
                server_memberships = ServerMember.query.filter(
                    ServerMember.guest_id == user_id
                ).all()
            elif userType == 'normalUser':
                server_memberships = ServerMember.query.filter(
                    ServerMember.user_id == user_id
                ).all()

            server_ids = [sm.server_id for sm in server_memberships]

            server_data = []
            for serverMem in server_memberships:
                actChannel = serverMem.actChannel
                server = Server.query.filter_by(server_id=serverMem.server_id).first()

                # 查询服务器成员数量
                members_count = ServerMember.query.filter(
                    ServerMember.server_id == serverMem.server_id
                ).count()

                server_data.append({
                    'server_id': server.server_id,
                    'name': server.name,
                    'is_default': server.is_default,
                    'members_count': members_count,
                    'created_at': server.created_at.isoformat(),
                    'actChannel': actChannel,
                    'owner_id': server.owner_id
                })

            # 将默认服务器放在列表最前面
            server_data.sort(key=lambda x: not x['is_default'])

            return server_data
        except Exception as e:
            # 记录详细错误日志
            db.session.rollback()
            # 实际应用中应使用日志框架记录错误
            print(f"Error retrieving servers: {str(e)}")
            return None

    @staticmethod
    def get_channel_by_server(server_id: str,curUser_id:str):
        """
        根据服务器ID获取该服务器所有频道
        包括服务器基本信息、频道和成员
        """
        try:
            # 加载频道
            channels = Channel.query.filter_by(server_id=server_id).all()

            channel_data = []
            for channel in channels:
                channel_data.append({
                    'server_id': channel.server_id,
                    'channel_id': channel.channel_id,
                    'name': channel.name,
                    'type': channel.type,
                    'position': channel.position,
                    'created_at': channel.created_at.isoformat(),
                })

            # 查询服务器成员
            member_data = []
            memberList = ServerMember.query.filter_by(server_id=server_id).all()
            for member in memberList:
                user = None
                avatar_url = ''
                username = ''
                status = 'offline'
                if member.user_id:
                    user = User.query.filter_by(user_id=member.user_id).first()
                    avatar_url = user.avatar_url
                    username = user.username
                    status = user.status

                friend = Friend.query.filter_by(user_id=curUser_id,friend_id=member.user_id).first()
                friendR = Friend.query.filter_by(user_id=member.user_id,friend_id=curUser_id).first()
                if friend and friendR:
                    isFriend = True
                else:
                    isFriend = False

                member_data.append({
                    'membership_id': member.membership_id,
                    'server_id': member.server_id,
                    'user_id': member.user_id,
                    'username': username,
                    'guest_id': member.guest_id,
                    'role': member.role,
                    'joined_at': member.joined_at,
                    'can_leave': member.can_leave,
                    'avatar_url': avatar_url,
                    'status': status,
                    'isFriend': isFriend,
                })

            return channel_data,member_data
        except Exception as e:
            # 记录详细错误日志
            db.session.rollback()
            # 实际应用中应使用日志框架记录错误
            print(f"Error retrieving servers: {str(e)}")
            return None

    @staticmethod
    def change_act_scF(actServerId,actChannelId,userId,userType):
        """修改用户活跃服务器和频道"""

        if userType == 'guestUser':
            user = GuestUser.query.filter_by(guest_id=userId).first()
            server_membership = ServerMember.query.filter_by(server_id=actServerId,guest_id=userId).first()

        elif userType == 'normalUser':
            user = User.query.filter_by(user_id=userId).first()
            server_membership = ServerMember.query.filter_by(server_id=actServerId,user_id=userId).first()

        if actChannelId and server_membership:
            server_membership.actChannel = actChannelId
            db.session.commit()

        if actServerId and user:
            user.actServer = actServerId
            db.session.commit()

        return '修改成功'

    @staticmethod
    def getInviteCode(server_id):
        server = Server.query.filter_by(server_id=server_id).first()
        if server:
            return server.invite_code
        else:
            return None

    @staticmethod
    def changeServerName(server_id,name):
        server = Server.query.filter_by(server_id=server_id).first()
        server.name = name
        db.session.commit()

        return 'success'

    @staticmethod
    def addServerChannel(server_id,type,name,user_id,descripe=''):
        server = Server.query.filter_by(server_id=server_id).first()
        if user_id != server.owner_id:
            return '未授权',401

        channel_count = Channel.query.filter_by(server_id=server_id,type=type).count()

        server_menbers = ServerMember.query.filter_by(server_id=server_id).all()

        new_channel = Channel(
            channel_id=str(uuid.uuid4()),
            server_id=server_id,
            name=name,
            type=type,
            position=int(channel_count + 1),
            descripe=descripe,
        )
        db.session.add(new_channel)

        #添加服务器成员频道权限
        for member in server_menbers:
            permission = ChannelPermission(
                permission_id=str(uuid.uuid4()),
                channel_id=new_channel.channel_id,
                member_id=member.membership_id,
                can_manage=member.role!='member',
                can_view=True,
                can_send=True,  # 文本频道可发送消息
                can_connect=True  # 语音频道可连接
            )
            db.session.add(permission)

        db.session.commit()

        return new_channel

    @staticmethod
    def getChannelInfo(channel_id):
        channel = Channel.query.filter_by(channel_id=channel_id).first()
        channel_count = Channel.query.filter_by(server_id=channel.server_id, type=channel.type).count()
        channel = {
            'server_id':channel.server_id,
            'channel_id':channel.channel_id,
            'name':channel.name,
            'type':channel.type,
            'descripe':channel.descripe,
            'position':channel.position,
            'created_at':channel.created_at,
            'channel_count':int(channel_count),
        }
        return channel

    @staticmethod
    def editChannelInfo(channel_id: str, position: int, descripe: str, name: str,user_id:str):
        try:
            with db.session.begin_nested():
                channel = Channel.query.filter_by(channel_id=channel_id).with_for_update().first()
                serverMember = ServerMember.query.filter_by(server_id=channel.server_id,user_id=user_id).first()

                print(serverMember.role)
                if serverMember.role =='member':
                    return '无权操作',403
                if not channel:
                    return '频道不存在', 404

                all_channels = Channel.query.filter_by(
                    server_id=channel.server_id,
                    type=channel.type
                ).order_by(Channel.position.asc()).all()

                # 验证新位置范围（从1开始）
                if position < 1 or position > len(all_channels):
                    return f'位置值无效，必须介于1-{len(all_channels)}之间', 400

                # 查找当前频道的旧位置索引
                old_index = next((i for i, c in enumerate(all_channels) if c.channel_id == channel_id), None)
                if old_index is None:
                    return '频道位置数据异常', 500

                # 转换索引到1起始的位置值
                old_position = old_index + 1

                # 如果位置发生变化
                if old_position != position:
                    # 移除当前频道
                    removed_channel = all_channels.pop(old_index)

                    # 插入到新位置（调整索引）
                    all_channels.insert(position - 1, removed_channel)

                    # 重新为所有频道分配唯一的位置值
                    for index, ch in enumerate(all_channels):
                        ch.position = index + 1  # 从1开始

                # 更新频道信息
                channel.name = name.strip()
                channel.descripe = descripe.strip() if descripe else None
                if not channel.name:
                    return '频道名称不能为空', 400
            db.session.commit()
            return {
                'channel_id': channel.channel_id,
                'name': channel.name,
                'position': channel.position,  # 返回1起始的位置
                'descripe': channel.descripe,
                'server_id': channel.server_id
            }

        except Exception as e:
            db.session.rollback()
            print(f"编辑频道错误: {str(e)}")
            return f'更新失败: {str(e)}', 500

    @staticmethod
    def deleteChannel(channel_id,user_id):
        channel = Channel.query.filter_by(channel_id=channel_id).with_for_update().first()
        channelCount = Channel.query.filter_by(server_id=channel.server_id,type=channel.type).count()
        member = ServerMember.query.filter_by(server_id=channel.server_id,user_id=user_id).first()
        channelPermission = ChannelPermission.query.filter_by(channel_id=channel_id).first()

        if member.role != 'owner':
            return '无权操作',403

        if channelCount <= 1:
            return '无法删除最后一个频道',403

        try:
            db.session.delete(channelPermission)
            db.session.delete(channel)
            if member.actChannel == channel_id:
                channels = Channel.query.filter_by(server_id=channel.server_id,type='text').first()
                member.actChannel = channels.channel_id

            db.session.commit()
            return '删除成功'
        except Exception as e:
            db.session.rollback()
            print(f"删除频道错误: {str(e)}")
            return f'删除失败', 500

    @staticmethod
    def getUserServerInfo(user_id,server_id,userType):
        server = Server.query.filter_by(server_id=server_id).first()

        if userType=='guestUser':
            serverMember = ServerMember.query.filter_by(guest_id=user_id, server_id=server_id).first()
            user = GuestUser.query.filter_by(guest_id=user_id).first()
            user_id = user.guest_id
            username = '游客'
        elif userType == 'normalUser':
            serverMember = ServerMember.query.filter_by(user_id=user_id, server_id=server_id).first()
            user = User.query.filter_by(user_id=user_id).first()
            user_id = user.user_id
            username = user.username
        if not user:
            return '未知错误',400
        if not server or not serverMember:
            return '不存在该服务器',404

        channel = Channel.query.filter_by(channel_id=serverMember.actChannel).first()

        result_data = {
            'server_id':server.server_id,
            'actChannel':serverMember.actChannel,
            'actChannelType':channel.type,
            'server_name':server.name,
            'role':serverMember.role,
            'can_leave':serverMember.can_leave,
            'user_id':user_id,
            'username':username,
        }

        return result_data

    @staticmethod
    def getChannelMembers(channel_id):
        try:
            channelPermission = ChannelPermission.query.filter_by(channel_id=channel_id).all()
            channelType = Channel.query.filter_by(channel_id=channel_id).first().type

            memberList = []
            for permit in channelPermission:
                member = ServerMember.query.filter_by(membership_id=permit.member_id).first()

                if member.user_id:
                    user_id = member.user_id
                    user = User.query.filter_by(user_id=user_id).first()
                    avatarUrl = user.avatar_url
                    userType = 'normalUser'
                    username = user.username
                else:
                    user_id = member.guest_id
                    user = GuestUser.query.filter_by(guest_id=user_id).first()
                    avatarUrl = ''
                    userType = 'guestUser'
                    username = '游客'

                memberList.append({
                    'user_id': user_id,
                    'member_id': permit.member_id,
                    'username':username,
                    'avatarUrl':avatarUrl,
                    'channel_id': permit.channel_id,
                    'channelType': channelType,
                    'userType': userType,
                    'role': member.role,
                    'can_view': permit.can_view,
                    'can_send':permit.can_send,
                    'can_manage':permit.can_manage,
                    'can_connect':permit.can_connect,
                    'is_muted':permit.is_muted,
                })



            return memberList

        except Exception as e:
            print(f"获取频道成员信息错误: {str(e)}")
        return f'获取频道成员信息错误', 500

    @staticmethod
    def editMemberPermission(channel_id:str,member_id:str,option:str,value:bool,operate_user:str):
        try:
            member = ServerMember.query.filter_by(user_id=operate_user).first()
            print(member.role,member_id)
            if member.role == 'member':
                return '无权修改',402

            permit = ChannelPermission.query.filter_by(channel_id=channel_id,member_id=member_id).first()
            if option == 'can_view':
                permit.can_view = value
            if option == 'can_send':
                permit.can_send = value
            if option == 'can_manage':
                permit.can_manage = value
            if option == 'can_connect':
                permit.can_connect = value
            if option == 'is_muted':
                permit.is_muted = value

            db.session.commit()
            return '修改成功'

        except Exception as e:
            print(f"修改成员权限错误: {str(e)}")
        return f'修改成员权限错误', 500